4장. 파이썬으로 숫자 다루기 (NumPy·PyTorch)

출처: 『AI 엔지니어링 선수지식』(youtubedu 자체 제작 학습노트) | 입문판 재구성 — 노트가 1차 소스(PDF 원본 없음)

코드는 분위기만 — np·torch·import 같은 말은 몰라도 됩니다. 표의 '비유'와 '위험'만 봐도 충분해요.


이 장은 도구 이야기다.

앞 장들에서 숫자·방향·확률을 손으로 풀어 봤다.

이제 그 계산을 컴퓨터에게 시키는 두 도구를 만난다.

하나는 NumPy, 하나는 PyTorch다.

둘 다 하는 일은 똑같다.

숫자 묶음(벡터·행렬)을 빠르게 다룬다.

겁먹지 말자.

새 개념은 거의 없고, 이미 아는 것을 더 빨리 하는 방법일 뿐이다.


0. 이 장의 새 단어 (0장에 없는 것만 3개)

0장 용어집은 그대로 쓴다.

여기서는 이 장에만 새로 나오는 도구 이름 3개만 푼다.


NumPy 배열 (ndarray)

한 문장 뜻 — 숫자를 격자로 담아 한 번에 계산하는 빠른 통.

일상비유 — 엑셀 시트의 코드 버전. 셀에 숫자를 채우고 버튼 한 번으로 전부 계산하는 그 느낌.

한 줄 예 —

# 숫자 묶음을 빠른 통에 담는다
a = np.array([1, 2, 3])

브로드캐스팅 (broadcasting)

한 문장 뜻 — 모양이 다른 두 묶음을 더하거나 곱할 때, 작은 쪽을 자동으로 늘려 맞추는 규칙.

일상비유 — 반 전원에게 +5점. 5라는 숫자 하나가 학생 수만큼 저절로 복사되어 더해진다.

한 줄 예 —

# 점수 3개에 5를 한 번에 더한다 (5가 자동 복사됨)
scores = np.array([80, 90, 70]) + 5   # [85 95 75]

PyTorch 텐서 / autograd

한 문장 뜻 — NumPy 배열에 GPU 가속과 자동 미분을 얹은 형(텐서). autograd는 그 자동 미분 기능.

일상비유 — NumPy가 보통 계산기라면, 텐서는 GPU로 빨라지고 미분까지 알아서 해 주는 고급 계산기.

한 줄 예 —

# requires_grad=True 를 붙이면 미분을 알아서 계산해 준다
x = torch.tensor(2.0, requires_grad=True)

이런 적 있죠?

학생 30명의 시험 점수가 있다.

전원에게 5점씩 더해 주고 싶다.

파이썬 기본 리스트로 하면 반복문을 돌려야 한다.

# 기본 리스트 — 한 명씩 돌면서 더한다
new_scores = [s + 5 for s in scores]

한 명, 또 한 명, 30번을 돈다.

30명이면 괜찮다.

그런데 1000만 명이면?

수백만 칸짜리 임베딩이면?

반복문이 너무 느려진다.

여기서 NumPy가 등판한다.

NumPy는 반복문 없이 묶음 전체를 한 줄로 계산한다.

# NumPy — 묶음 전체를 한 줄로
new_scores = np.array(scores) + 5

같은 일을 수십 배 빠르게 한다.

그게 이 장의 핵심이다.

한 문장 정의 — NumPy와 PyTorch는 숫자 묶음을 반복문 없이 한 번에, 그리고 빠르게 계산해 주는 AI의 손과 발이다.


이 장에서 딱 3가지만 (TL;DR)

  1. NumPy 배열 — 숫자를 격자에 담아 반복문 없이 한 줄로 계산한다.
  2. 브로드캐스팅 — 모양이 달라도 작은 쪽을 자동으로 늘려 맞춰 더한다.
  3. PyTorch 텐서·autograd — NumPy에 GPU와 자동 미분을 얹어, 미분을 손으로 안 짜도 된다.

이 셋만 손에 잡으면 AI 코드가 술술 읽힌다.


개념 1 — NumPy 배열 (숫자 격자)

막히는 장면

벡터 100만 개의 평균을 구해야 한다.

기본 리스트로는 for 문을 돌려야 한다.

칸이 많을수록 느려진다.

NumPy는 같은 일을 통째로, 빠르게 한다.

일상비유 — 엑셀의 코드 버전.

엑셀에서 한 열에 숫자를 쭉 채운다.

맨 아래에 =평균() 한 줄을 넣으면 끝이다.

한 칸씩 더하지 않는다.

NumPy 배열(ndarray)이 바로 그 엑셀을 코드로 옮긴 것이다.

숫자를 격자에 담고, 반복문 없이 한 줄로 연산한다.

비유 코드 위험
엑셀 시트 a = np.array([[1,2,3],[4,5,6]]) 기본 리스트보다 빠르지만, 일반 list와 섞어 쓰면 느려짐
=평균() 한 줄 a.mean(axis=0) axis(행/열 방향)를 헷갈리면 엉뚱한 평균이 나옴
조건 자동 추출 a[a > 3] 모양(shape)이 안 맞으면 계산이 막힘

한 문장 정의 — NumPy 배열(ndarray)은 숫자를 격자에 담아 반복문 없이 한 줄로 빠르게 계산하는 통이다.

단순 규칙 — 숫자가 여러 개면 일단 np.array에 담는다. 그게 시작이다.


예시 폭격 1 — NumPy 배열

예시 ① 완성 예 (worked) — 보고 따라 읽기

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])  # 2행 3열 격자
print(a.shape)         # (2, 3)  → 2행 3열이라는 뜻
print(a.mean(axis=0))  # [2.5 3.5 4.5]  → 열별 평균
print(a[a > 3])        # [4 5 6]  → 3보다 큰 칸만 골라냄

shape는 격자의 모양이다.

mean(axis=0)은 위아래(열) 방향 평균이다.

a[a > 3]은 조건에 맞는 칸만 한 줄로 뽑는다.

반복문이 한 줄도 없다.

예시 ② 일상 장면 — before / after

같은 일을 두 가지 방식으로 해 보자.

# before — 기본 리스트, 반복문 필요
nums = [1, 2, 3]
doubled = [x * 2 for x in nums]   # [2, 4, 6]
# after — NumPy, 한 줄
nums = np.array([1, 2, 3])
doubled = nums * 2                # [2 4 6]

결과는 똑같다.

코드는 더 짧고, 데이터가 커질수록 더 빠르다.

예시 ③ 부분 완성 — 빈칸 채우기

학생 점수 격자에서 "각 과목(열)의 평균"을 구하고 싶다.

빈칸 ____를 채워 보자.

scores = np.array([[90, 85, 100], [70, 95, 80]])
# 힌트: 위아래(열) 방향 평균은 axis=0
col_avg = scores.____(axis=0)

정답은 mean이다.

scores.mean(axis=0)[80. 90. 90.].

예시 ④ 독립 적용 — 스스로

배열 np.array([5, 1, 8, 3])에서 4보다 큰 값만 뽑는 한 줄을 떠올려 보자.

답: arr[arr > 4][5 8].

조건을 대괄호 안에 넣으면 자동으로 필터된다.

미니 시나리오 — "이럴 때 이렇게"

이미지 한 장을 다룰 때.

이미지는 결국 픽셀 숫자의 큰 격자다.

밝기를 전부 절반으로 줄이려면?

기본 리스트로는 픽셀 수만큼 반복문을 돈다.

NumPy로는 image = image * 0.5 한 줄이다.

이래서 데이터 전처리·통계·이미지 처리의 기본기가 전부 NumPy다.

실무 메모 — Pandas, scikit-learn, PyTorch가 전부 NumPy 위에 지어졌다. 임베딩·확률 묶음도 NumPy로 다룬다. 모든 묶음 연산의 출발점이다.

더 깊이 (지금 몰라도 됨)NumPy Absolute Beginners


개념 2 — 브로드캐스팅 (자동으로 모양 맞추기)

막히는 장면

학생 30명 점수에 전원 +5점을 하고 싶다.

머리로는 "5를 30번 복사해서 각자에게 더한다"고 생각하기 쉽다.

그런데 NumPy에서는 5를 30개로 만들 필요가 없다.

그냥 + 5 하면 알아서 늘려 맞춰 더한다.

이 "자동으로 모양 맞추기"가 브로드캐스팅이다.

일상비유 — 양념 한 스푼씩.

찌개 한 솥에 소금을 넣을 때.

국자마다 따로 소금을 넣지 않는다.

한 번 넣으면 솥 전체에 퍼진다.

브로드캐스팅도 똑같다.

숫자 하나(5)가 묶음 전체에 알아서 퍼져 더해진다.

비유 코드 위험
전원 +5점 np.array([80,90,70]) + 5 모양이 아예 안 맞으면(예: 3칸 + 4칸) 오류가 남
솥에 소금 퍼지기 M - M.mean(axis=0) axis를 잘못 잡으면 엉뚱한 방향으로 퍼짐
복사 안 해도 됨 작은 쪽이 자동으로 늘어남 늘어나는 규칙을 모르면 결과 모양을 예측 못 함

한 문장 정의 — 브로드캐스팅은 모양이 다른 두 묶음을 연산할 때 작은 쪽을 자동으로 늘려 맞춰 주는 규칙이다.

단순 규칙 — 숫자 하나를 묶음 전체에 더하거나 곱하고 싶으면, 그냥 더하거나 곱하면 된다. 늘리는 건 NumPy가 한다.


예시 폭격 2 — 브로드캐스팅

예시 ① 완성 예 (worked) — 전원 +5

import numpy as np

scores = np.array([[80], [90], [70]])  # 학생 3명, 세로 묶음
print(scores + 5)
# [[85]
#  [95]
#  [75]]

5라는 숫자 하나가 학생 수만큼 자동으로 퍼졌다.

5를 손으로 복사하지 않았다.

예시 ② 핵심 활용 — 평균 빼기(정규화 맛보기)

M = np.array([[1, 2, 3], [4, 5, 6]])
print(M - M.mean(axis=0))
# 각 열에서 그 열의 평균을 자동으로 뺀다

M.mean(axis=0)은 열별 평균(작은 묶음)이다.

그게 M(큰 묶음)의 모든 행에 자동으로 퍼져서 빼진다.

이게 정규화의 기본 동작이다.

예시 ③ 부분 완성 — 빈칸 채우기

온도 묶음 [20, 25, 30]에서 전부 10을 빼고 싶다.

temps = np.array([20, 25, 30])
result = temps ____ 10   # 빈칸을 채워라

정답은 -다.

temps - 10[10 15 20].

10 하나가 세 칸에 자동으로 퍼져 빠진다.

예시 ④ 독립 적용 — before / after

"가격 묶음 전체에 1.1을 곱해 10% 인상"을 떠올려 보자.

# before — 반복문
prices = [100, 200, 300]
raised = [p * 1.1 for p in prices]
# after — 브로드캐스팅
prices = np.array([100, 200, 300])
raised = prices * 1.1     # [110. 220. 330.]

1.1 하나가 모든 칸에 곱해진다.

미니 시나리오 — "이럴 때 이렇게"

문장 여러 개에 같은 가중치를 적용해야 할 때.

문장 100개를 한 격자(배치)에 쌓는다.

가중치 묶음 하나를 그 격자에 곱한다.

브로드캐스팅이 가중치를 100개 문장 전부에 자동으로 퍼뜨린다.

반복문 없이 한 줄로 끝난다.

실무 메모 — 정규화(평균 빼고 표준편차 나누기)가 전부 브로드캐스팅이라, 코드가 짧고 빨라진다.

한 걸음 더 ▸ (지금 몰라도 됨) — 모양을 어떻게 늘릴지에는 정해진 규칙이 있다. 칸 수가 1이거나 같으면 맞춰지고, 둘 다 아니면 오류가 난다. 지금은 "작은 쪽이 자동으로 퍼진다"만 기억하면 충분하다.


개념 3 — PyTorch 텐서·autograd (미분을 자동으로)

막히는 장면

앞에서 미분을 손으로 구했다.

y = x³의 미분은 3x²다.

그런데 AI 모델은 다이얼(가중치)이 수천억 개다.

수천억 개를 손으로 미분할 수는 없다.

여기서 PyTorch가 등판한다.

PyTorch에게 x만 넘기면, 미분을 알아서 계산해 준다.

이 자동 미분 기능이 autograd다.

일상비유 — NumPy의 형.

NumPy 배열이 보통 계산기라고 하자.

텐서는 그 계산기의 업그레이드 버전이다.

두 가지가 더 붙는다.

하나는 GPU 가속(아주 빠름), 하나는 자동 미분(autograd).

겉모습은 NumPy 배열과 거의 같다.

비유 코드 위험
업그레이드된 계산기 torch.tensor(2.0) NumPy와 비슷해 보여도 별도 도구라, 둘을 섞을 때 변환이 필요
미분 켜는 스위치 requires_grad=True 이 스위치를 안 켜면 미분(grad)이 안 나옴
미분 자동 계산 y.backward()x.grad backward()를 안 부르면 x.grad가 비어 있음

한 문장 정의 — PyTorch 텐서는 GPU 가속과 자동 미분(autograd)을 얹은 NumPy 배열이며, autograd 덕에 미분을 손으로 짤 필요가 없다.

단순 규칙 — 미분이 필요하면 텐서에 requires_grad=True를 켜고, backward()를 부른 뒤 .grad를 읽는다. 그 세 단계가 전부다.


예시 폭격 3 — PyTorch 텐서·autograd

예시 ① 완성 예 (worked) — 손 미분 vs 자동 미분

import torch

x = torch.tensor(2.0, requires_grad=True)  # 미분 스위치 ON
y = x ** 3                                   # y = x³
y.backward()                                 # 미분을 자동 계산
print(x.grad)                                # tensor(12.)

손으로 풀면 의 미분은 3x²다.

x = 2를 넣으면 3 × 2² = 12다.

PyTorch가 똑같이 12를 자동으로 내놓았다.

손 미분과 답이 같다.

예시 ② before / after — 손 vs PyTorch

# before — 손으로 미분 공식을 직접 짠다
def slope(x):
    return 3 * x ** 2     # x³ 의 미분 공식을 사람이 안다고 가정
print(slope(2.0))         # 12.0
# after — PyTorch가 공식을 몰라도 자동으로
x = torch.tensor(2.0, requires_grad=True)
(x ** 3).backward()
print(x.grad)             # tensor(12.)

before는 미분 공식을 사람이 알아야 한다.

after는 식만 적으면 PyTorch가 알아서 미분한다.

복잡한 식일수록 after의 이득이 커진다.

예시 ③ 부분 완성 — 빈칸 채우기

y = x²의 미분을 자동으로 구하고 싶다.

x = 3일 때 기울기는 2x = 6이어야 한다.

x = torch.tensor(3.0, requires_grad=True)
y = x ** 2
y.________()       # 빈칸: 미분을 계산하는 메서드
print(x.grad)      # tensor(6.)

정답은 backward다.

backward()를 불러야 x.grad에 값이 채워진다.

예시 ④ 독립 적용 — 스위치를 까먹으면?

x = torch.tensor(2.0)   # requires_grad 를 안 켰다
y = x ** 3
# y.backward()  ← 여기서 오류가 난다

requires_grad=True를 빠뜨리면 미분이 안 된다.

위험 표의 "스위치를 안 켜면 grad가 안 나옴"이 바로 이 상황이다.

스위치부터 켜는 습관이 안전판이다.

미니 시나리오 — "이럴 때 이렇게"

거대 모델이 틀린 답을 냈다.

어느 다이얼을 어느 쪽으로 돌릴지 알아야 한다.

다이얼이 수천억 개다.

손 미분은 불가능하다.

PyTorch는 모델 전체에 backward() 한 번을 불러, 모든 다이얼의 그래디언트를 자동으로 채운다.

그래서 모든 딥러닝 모델이 PyTorch(또는 비슷한 도구)로 작성된다.

실무 메모 — 모든 LLM이 텐서로 구현된다. autograd가 미분과 역전파를 자동화해, 사람이 그 계산을 손으로 짤 필요가 없다.

더 깊이 (지금 몰라도 됨)PyTorch Learn the Basics


정리

세 줄로 끝낸다.

NumPy 배열은 숫자를 격자에 담아 반복문 없이 한 줄로 빠르게 계산한다.

브로드캐스팅은 모양이 달라도 작은 쪽을 자동으로 늘려 맞춰 준다.

PyTorch 텐서는 NumPy에 GPU와 자동 미분(autograd)을 얹어, 미분을 손으로 안 짜게 해 준다.

도구 한마디
NumPy 배열 숫자 묶음 빠르게 다루기 (벡터·행렬)
브로드캐스팅 모양 자동 맞춤 (정규화·배치)
PyTorch 텐서 GPU 가속 배열
autograd 미분·역전파 자동화

한 문장으로, NumPy로 숫자를 빠르게, PyTorch로 GPU와 자동 미분까지.

이 둘이 AI 코드의 손과 발이다.


다음 장 예고 — 다음 장에서는 지금까지 모은 조각(숫자·방향·확률·도구)이 실제 AI 안에서 어떻게 한 흐름으로 이어지는지 본다. 지금은 이 장 도구 3개만 머리에 있으면 충분하다.

난이도
에피소드
질문
카드를 로딩 중...
답변

클릭하거나 Space를 눌러 뒤집기

0 / 0
학습 진도 0%
이동   Space 뒤집기   R 셔플